package com.lg.demo;


import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.*;

import java.io.IOException;
import java.util.Map;
/*
client.indices().create()
client.indices().delete()
client.get()
client.index()
*/

public class HighClient {
    RestHighLevelClient client;
    @Before
    public void init(){
        RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
                new HttpHost("zb26105", 9200, "http"),
                new HttpHost("zb26106", 9200, "http"),
                new HttpHost("zb26107", 9200, "http")
        ));
//        System.out.println(highLevelClient.cluster().toString());
        client = highLevelClient;
    }

    //创建索引
    @Test
    public void createIndex() {
        final CreateIndexRequest indexRequest = new CreateIndexRequest("es_test");
        //准备mapping映射信息
        String str = "{\n" +
                " \"settings\": {},\n" +
                " \"mappings\": {\n" +
                " \"properties\": {\n" +
                " \"description\": {\n" +
                " \"type\": \"text\",\n" +
                " \"analyzer\": \"ik_max_word\"\n" +
                " },\n" +
                " \"name\": {\n" +
                " \"type\": \"text\"\n" +
                " },\n" +
                " \"pic\": {\n" +
                " \"type\": \"text\",\n" +
                " \"index\": false\n" +
                " },\n" +
                " \"studymodel\": {\n" +
                " \"type\": \"text\"\n" +
                " }\n" +
                " }\n" +
                " }\n" +
                " }";

        //把映射信息添加到request对象中
        indexRequest.source(str, XContentType.JSON);

        //
        try {
            final CreateIndexResponse createIndexResponse = client.indices().create(indexRequest, RequestOptions.DEFAULT);
            final boolean acknowledged = createIndexResponse.isAcknowledged();
            System.out.println("创建结果："+acknowledged);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //删除索引
   @Test
   public void deleteIndex() throws IOException {
       DeleteIndexRequest indexRequest = new DeleteIndexRequest("es_test_1");
       AcknowledgedResponse delete = client.indices().delete(indexRequest, RequestOptions.DEFAULT);
       boolean acknowledged = delete.isAcknowledged();
       //是否成功删除的标志
       System.out.println(acknowledged);
   }


   //添加doc
    @Test
   public void addDoc() throws IOException {
        //准备一个添加文档的对象
        IndexRequest indexRequest = new IndexRequest("es_test").id("1");
        /*
        {
            "name": "spark添加文档",
                    "description": "spark技术栈",
                    "studymodel":"online",
                    "pic": "http://www.baidu.com"
        }
        */

        String str = " {\n" +
                " \"name\": \"spark添加文档\",\n" +
                " \"description\": \"spark技术栈\",\n" +
                " \"studymodel\":\"online\",\n" +
                " \"pic\": \"http://www.baidu.com\"\n" +
                " }";
        indexRequest.source(str,XContentType.JSON);

        //执行添加操作
        IndexResponse index = client.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(index.status());

    }

    //查询文档
    @Test
    public void getDoc() throws IOException {
        //准备一个查询的reqeust请求
        GetRequest getRequest = new GetRequest("es_test");
        //设定id
        getRequest.id("1");
        //执行查询
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
        System.out.println(sourceAsMap);
    }

     //查询文档
     @Test
     public void getAllDoc() throws IOException {
         // 构建一个searchRequest对象
         SearchRequest searchRequest = new SearchRequest();
         // 指定索引
         searchRequest.indices("es_test");
         //指定查询条件 matchall
         SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
         sourceBuilder.query(QueryBuilders.matchAllQuery());
         searchRequest.source(sourceBuilder);
         //执行检索 RequestOptions options参数: 请求选项(例如请求头),如果不需要自定义任何内容,使用RequestOptions.DEFAULT
         SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
         //解析响应结果
         final RestStatus status = response.status();
         System.out.println("查询结果状态："+status);
         SearchHits hits = response.getHits();
         SearchHit[] hits1 = hits.getHits();
         for (SearchHit searchHit : hits1) {
             Map<String, Object> map = searchHit.getSourceAsMap();
             for (Map.Entry<String, Object> entry : map.entrySet()) {
                 System.out.println("查询的字段："+entry.getKey()+"，字段的value值："+entry.getValue());
             }
         }

     }

    //根据关键字 不分词检索
     @Test
     public void termQuery() throws IOException {
         // 构建一个searchRequest对象
         SearchRequest searchRequest = new SearchRequest("es_test");

         SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
         sourceBuilder.query(QueryBuilders.termQuery("studymodel","online"));

         searchRequest.source(sourceBuilder);
         SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

         RestStatus status = response.status();
         System.out.println("查询状态："+status);

         SearchHits hits = response.getHits();
         SearchHit[] hits1 = hits.getHits();
         System.out.println("数组的长度:"+hits1.length);
         for (SearchHit searchHit : hits1) {
             Map<String, Object> map = searchHit.getSourceAsMap();
             for (Map.Entry<String, Object> entry : map.entrySet()) {
                 System.out.println("查询字段:"+entry.getKey()+"，字段值:"+entry.getValue());
             }
         }
     }

     //分页查询，返回第几页的记录
    @Test
    public void getAllDocWithPage() throws IOException {
        // 构建一个searchRequest对象
        SearchRequest searchRequest = new SearchRequest("es_test");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());

        //指定分页  from(0)表示第0页，size(1)表示每页展示1条数据
        sourceBuilder.from(0);
        sourceBuilder.size(1);
        //
        searchRequest.source(sourceBuilder);
        //执行检索
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        RestStatus status = response.status();
        System.out.println("查询状态："+status);

        SearchHits hits = response.getHits();
        SearchHit[] hits1 = hits.getHits();
//        System.out.println("数组的长度:"+hits1.length);
        for (SearchHit searchHit : hits1) {
            Map<String, Object> map = searchHit.getSourceAsMap();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                System.out.println("查询字段:"+entry.getKey()+"，字段值:"+entry.getValue());
            }

        }

    }

    //对返回的source字段进行过滤
    @Test
    public  void searchWithLimit() throws IOException {
        // 构建一个searchRequest对象
        SearchRequest searchRequest = new SearchRequest("es_test");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());

        //
        final String[] includeArr={"name"};
        final String[] excludeArr={};
        sourceBuilder.fetchSource(includeArr,excludeArr);

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        RestStatus status = response.status();
        System.out.println("查询状态："+status);

        SearchHits hits = response.getHits();
        SearchHit[] hits1 = hits.getHits();
        for (SearchHit searchHit : hits1) {
            Map<String, Object> map = searchHit.getSourceAsMap();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                System.out.println("查询字段:"+entry.getKey()+"，字段值:"+entry.getValue());
            }

        }
    }


    //排序 sort
    @Test
    public void searchWithSort() throws IOException {
        // 构建一个searchRequest对象
        SearchRequest searchRequest = new SearchRequest("book");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        //指定排序规则
        sourceBuilder.sort(new FieldSortBuilder("price").order(SortOrder.DESC));

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        RestStatus status = response.status();
        System.out.println("查询状态："+status);

        SearchHits hits = response.getHits();
        SearchHit[] hits1 = hits.getHits();
        for (SearchHit searchHit : hits1) {
            Map<String, Object> map = searchHit.getSourceAsMap();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                System.out.println("查询字段:"+entry.getKey()+"，字段值:"+entry.getValue());
            }

        }
    }

     //聚合分析
    //按照name分组，对组内计算一个avg的price
    @Test
    public void searchAgg() throws IOException {
        // 构建一个searchRequest对象
        SearchRequest searchRequest = new SearchRequest("book");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("name_group").field("name");
        aggregationBuilder.subAggregation(AggregationBuilders.avg("avg_price").field("price"));
        sourceBuilder.aggregation(aggregationBuilder);

        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest,
                RequestOptions.DEFAULT);
        //解析响应结果
        Terms name_group = searchResponse.getAggregations().get("name_group");
        for (Terms.Bucket bucket : name_group.getBuckets()) {
            Object key = bucket.getKey();
            Avg avg_price = bucket.getAggregations().get("avg_price");
            System.out.println("name：" + key + ",平均价格：" + avg_price.getValue());
        }

    }

    @After
    public  void destory(){
        if (client!=null){
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
